/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012 Oliver Katz */

#include "display_engine_loader.h"

namespace sleepyface
{
	namespace visual
	{
		namespace display_engine
		{
			DisplayEngineLoader::DisplayEngineLoader()
			{
				handle = NULL;
			}

			DisplayEngineLoader::DisplayEngineLoader(string path)
			{
				handle = dlopen(path.c_str(), RTLD_LAZY);
				if (handle == NULL)
				{
					cout << "error: " << dlerror() << "\n";
				}
			}

			DisplayEngineLoader::~DisplayEngineLoader()
			{
				if (handle != NULL)
					dlclose(handle);
			}

			bool DisplayEngineLoader::good()
			{
				return (handle != NULL);
			}

			vector<string> DisplayEngineLoader::listWidgetRenderers()
			{
				vector<string> rtn;
				if (handle == NULL)
					return rtn;
				lister lr = (lister)dlsym(handle, "_list_widgets");
				if (lr == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return rtn;
				}
				char **l = lr();
				if (l == NULL)
				{
					cout << "error: no container list\n";
					return rtn;
				}
				for (int i = 0; l[i] != NULL; i++)
					rtn.push_back(string(l[i]));
				return rtn;
			}

			vector<string> DisplayEngineLoader::listContainerRenderers()
			{
				vector<string> rtn;
				if (handle == NULL)
					return rtn;
				lister lr = (lister)dlsym(handle, "_list_containers");
				if (lr == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return rtn;
				}
				char **l = lr();
				if (l == NULL)
				{
					cout << "error: no container list\n";
					return rtn;
				}
				for (int i = 0; l[i] != NULL; i++)
					rtn.push_back(string(l[i]));
				return rtn;
			}

			WidgetRenderer DisplayEngineLoader::getWidgetRenderer(string n)
			{
				WidgetSizeCallback wsc = (WidgetSizeCallback)dlsym(handle, ("_widgetsize_"+n).c_str());
				if (wsc == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return WidgetRenderer();
				}

				WidgetRenderCallback wrc = (WidgetRenderCallback)dlsym(handle, ("_widgetrender_"+n).c_str());
				if (wrc == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return WidgetRenderer();
				}

				return WidgetRenderer(wsc, wrc);
			}

			ContainerRenderer DisplayEngineLoader::getContainerRenderer(string n)
			{
				ContainerSizeCallback wsc = (ContainerSizeCallback)dlsym(handle, ("_containersize_"+n).c_str());
				if (wsc == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return ContainerRenderer();
				}

				ContainerHinterCallback whc = (ContainerHinterCallback)dlsym(handle, ("_containerhint_"+n).c_str());
				if (whc == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return ContainerRenderer();
				}

				ContainerRenderCallback wrc = (ContainerRenderCallback)dlsym(handle, ("_containerrender_"+n).c_str());
				if (wrc == NULL)
				{
					cout << "error: " << dlerror() << "\n";
					return ContainerRenderer();
				}

				return ContainerRenderer(wsc, whc, wrc);
			}
		}
	}
}
